home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 22 / Cream of the Crop 22.iso / os2 / edm0407s.zip / SEMSRC.ZIP / SYNC.H < prev   
C/C++ Source or Header  |  1996-06-26  |  10KB  |  521 lines

  1. /*  -*- C++ -*-
  2.  
  3.     $Author: Eddy_Kim $
  4.  
  5.     $Id: sync.h 1.8 1996/06/21 08:01:45 Eddy_Kim Exp Eddy_Kim $
  6.     $Revision: 1.8 $
  7.  
  8.     Copyright 1996
  9.     Eddy Kim
  10.  
  11.     Synchronization classes:
  12.       mutex, Event semaphores, locks, multiple event/mutex wait,
  13.       reader/writer mutex
  14. */
  15.  
  16. #ifndef SYNC_H
  17. #define SYNC_H
  18.  
  19. #define INCL_BASE
  20. #include <os2.h>
  21.  
  22. #include <iostream.h>
  23.  
  24. class Semaphore
  25. {
  26. public:
  27.     Semaphore(HSEM hSem=0, ULONG udd=0);
  28.     Semaphore(const Semaphore& aSem);
  29.     virtual ~Semaphore()=0;
  30.  
  31.     HSEM GetHandle() const;
  32.     ULONG GetUDD() const;
  33.     void SetUDD(ULONG udd);
  34. protected:
  35.     SEMRECORD sem_;
  36.  
  37.     HSEM* GetPHSEM();      // return a pointer to the semaphore handle
  38.     HSEM GetHSEM() const;  // return the semaphore handle
  39.     ULONG* GetPUDD();      // return a pointer to user defined data
  40.     ULONG GetUDD() const;  // return user defined data
  41. private:
  42. };
  43.  
  44. /*
  45.    mutual exclusion class.
  46.    When entering an exclusive code region, or using a limited resource,
  47.    use the Mutex to prevent others from entering that area.
  48.    OS/2 Mutex locks are recursive.  Find out the number of recursive locks
  49.    are set by QueryOwner in the count variable.
  50.  */
  51. class Mutex: public Semaphore
  52. {
  53. public:
  54.     enum Openmode
  55.     {
  56.     OPEN,
  57.     CREATE,
  58.     DONTCARE
  59.     };
  60.     enum Attr
  61.     {
  62.     SHARED=DC_SEM_SHARED,
  63.     PRIVATE=0,
  64.     DEFAULTATTR=SHARED
  65.     };
  66.     enum InitState
  67.     {
  68.     OWNED=1,
  69.     UNOWNED=0,
  70.     DEFAULTSTATE=UNOWNED
  71.     };
  72.  
  73.     Mutex();
  74.     Mutex(HMTX mtx);
  75.     Mutex(const Mutex& mtx);
  76.     Mutex(string& mtxname,
  77.       Openmode mode=DONTCARE,
  78.       ULONG attr=DEFAULTATTR,
  79.       BOOL32 state=DEFAULTSTATE);
  80.     virtual ~Mutex();
  81.  
  82.     APIRET QueryOwner(PPID pid, PTID tid, PULONG count) const;
  83.     APIRET Release();
  84.     virtual APIRET Request(ULONG timeout=SEM_INDEFINITE_WAIT);
  85.  
  86. protected:
  87. private:
  88.     Mutex operator=(const Mutex& mtx); // don't allow assignment
  89.  
  90.     APIRET Open(string& mtxname);
  91.     APIRET Create(string& mtxname, ULONG attr, BOOL32 state);
  92. };
  93.  
  94.  
  95. /*
  96.    Use this to automatically grab and release a lock in a
  97.    code block.  Careful when grabbing multiple locks.  Deadlock!
  98.    example:
  99.      {
  100.        MutexLock lock(aMutex);
  101.        ... do some stuff.
  102.      } .. automatically release lock.
  103.  */
  104. class MutexLock
  105. {
  106. public:
  107.     MutexLock(Mutex& mtx);
  108.     MutexLock(Mutex* mtx);
  109.     ~MutexLock();
  110. protected:
  111. private:
  112.     Mutex& mutex;
  113.     operator=(const MutexLock&);
  114. };
  115.  
  116. /*
  117.    Event semaphore class.
  118.    Used to notify asychronous threads/processes, that an event has occured.
  119.    when the semaphore is set (zero) threads can do a blocking Wait()
  120.    call, until posted.
  121.  */
  122. class Event: public Semaphore
  123. {
  124. public:
  125.     enum Openmode
  126.     {
  127.     OPEN,
  128.     CREATE,
  129.     DONTCARE
  130.     };
  131.     enum Attr
  132.     {
  133.     SHARED=DC_SEM_SHARED,
  134.     PRIVATE=0,
  135.     DEFAULTATTR=SHARED
  136.     };
  137.     enum InitState
  138.     {
  139.     OWNED=1,
  140.     UNOWNED=0,
  141.     DEFAULTSTATE=UNOWNED
  142.     };
  143.     Event();
  144.     Event(const Event&);
  145.     Event(string& name,
  146.       Openmode mode=DONTCARE,
  147.       ULONG attr=DEFAULTATTR,
  148.       BOOL32 state=DEFAULTSTATE);
  149.     virtual ~Event();
  150.  
  151.     APIRET Post();  // causes blocked threads to execute
  152.     virtual APIRET Wait(ULONG timeout=SEM_INDEFINITE_WAIT);
  153.     APIRET Query(ULONG* postCount);
  154.     APIRET Reset(ULONG* postCount=0);// threads that wait on a reset sem, block
  155. protected:
  156. private:
  157.     APIRET Open(string& name);
  158.     APIRET Create(string& name, ULONG attr, BOOL32 state);
  159. };
  160.  
  161.  
  162. #define INLINE inline
  163.  
  164. INLINE Semaphore::Semaphore(HSEM hSem, ULONG udd)
  165. {
  166.     sem_.hsemCur=hSem;
  167.     sem_.ulUser=udd;
  168. }
  169.  
  170. INLINE Semaphore::Semaphore(const Semaphore& aSem)
  171. {
  172.     sem_.hsemCur=aSem.GetHSEM();
  173.     sem_.ulUser=aSem.GetUDD();
  174. }
  175.  
  176. INLINE Semaphore::~Semaphore()
  177. {
  178. }
  179.  
  180. INLINE HSEM Semaphore::GetHandle() const
  181. {
  182.     return GetHSEM();
  183. }
  184.  
  185. INLINE void Semaphore::SetUDD(ULONG udd)
  186. {
  187.     *GetPUDD()=udd;
  188. }
  189.  
  190. INLINE HSEM* Semaphore::GetPHSEM()
  191. {
  192.     return &sem_.hsemCur;
  193. }
  194.  
  195. INLINE HSEM Semaphore::GetHSEM() const
  196. {
  197.     return sem_.hsemCur;
  198. }
  199.  
  200. INLINE ULONG* Semaphore::GetPUDD()
  201. {
  202.     return &sem_.ulUser;
  203. }
  204.  
  205. INLINE ULONG Semaphore::GetUDD() const
  206. {
  207.     return sem_.ulUser;
  208. }
  209.  
  210. /*
  211.    Default mutex contructor.  Creates a non-named shared semaphore.
  212.  */
  213. INLINE Mutex::Mutex(): Semaphore()
  214. {
  215.     APIRET rc=0;
  216.     // create an unnamed mutex
  217.     rc=DosCreateMutexSem(NULL,(PHMTX)GetPHSEM(),DEFAULTATTR,DEFAULTSTATE);
  218.     if (rc!=0)
  219.     {
  220.         cerr<<"Error"<<endl;
  221.     }
  222. }
  223.  
  224. /*
  225.    Construct a mutex object from an already opened or created mutex handle.
  226.    It does not take ownership/responsibility for the passed in handle.
  227.  */
  228. INLINE Mutex::Mutex(HMTX mtx): Semaphore((HSEM)mtx)
  229. {
  230.     APIRET rc=DosOpenMutexSem(NULL,(PHMTX)GetPHSEM());  // open it so that when the
  231.     // object destructs, the correct semantics happen (DosCloseMutexSem).
  232.     if (rc!=0)
  233.     {
  234.         // Error.
  235.         cerr<<"Error"<<endl;
  236.     }
  237. }
  238.  
  239. /*
  240.    Opens the passed in mutex by the mutex handle.
  241.  */
  242. INLINE Mutex::Mutex(const Mutex& mtx): Semaphore(mtx)
  243. {
  244.     APIRET rc;
  245.     rc=DosOpenMutexSem(NULL,(PHMTX)GetPHSEM());
  246.     if (rc!=0)
  247.     {
  248.         // Error.
  249.         cerr<<"Error"<<endl;
  250.     }
  251. }
  252.  
  253. /*
  254.    constructor.  Creates or opens a mutex.  If the string is 0 length,
  255.    it creates a mutex with no name.  If string is non-zero, it first attempts
  256.    to open the mutex by name, and if that fails, it will create the mutex.
  257.    If created by name, it will only be able to be copied by handle.
  258.  */
  259. INLINE Mutex::Mutex(string& mtxname,
  260.             Openmode mode,
  261.             ULONG attr,
  262.             BOOL32 state): Semaphore()
  263. {
  264.     APIRET rc=0;
  265.  
  266.     switch (mode)
  267.     {
  268.     case DONTCARE:
  269.     case OPEN:
  270.     if ((mode==OPEN) && (mtxname.length()==0))
  271.     {
  272.         // unnamed semaphore == error
  273.         // to open an unnamed, shared semaphore, use the Mutex(HSEM) ctor
  274.         // Error.
  275.         cerr<<"Error"<<endl;
  276.     }
  277.  
  278.     rc=Open(mtxname);
  279.     if (rc==0)
  280.         break;
  281.     if (mode==OPEN)
  282.     {
  283.         if (rc!=0)
  284.         {
  285.             // Error.
  286.         cerr<<"Error"<<endl;
  287.         }
  288.         break;
  289.     }
  290.     case CREATE:
  291.     rc=Create(mtxname,attr,state);
  292.     if (rc!=0)
  293.     {
  294.         // Error.
  295.         cerr<<"Error"<<endl;
  296.     }
  297.     break;
  298.     default:
  299.         // Error.
  300.     ;
  301.         cerr<<"Error"<<endl;
  302.     }
  303. }
  304.  
  305. INLINE Mutex::~Mutex()
  306. {
  307.     APIRET rc=DosCloseMutexSem((HMTX)GetHSEM());
  308.     if (rc!=0)
  309.     {
  310.     // Error.
  311.         cerr<<"Error"<<endl;
  312.     }
  313. }
  314. INLINE APIRET Mutex::QueryOwner(PPID pid, PTID tid, PULONG count) const
  315. {
  316.     return DosQueryMutexSem((HMTX)GetHSEM(),pid,tid,count);
  317. }
  318. INLINE APIRET Mutex::Release()
  319. {
  320.     return DosReleaseMutexSem((HMTX)GetHSEM());
  321. }
  322. INLINE APIRET Mutex::Request(ULONG timeout)
  323. {
  324.     return DosRequestMutexSem((HMTX)GetHSEM(), timeout);
  325. }
  326.  
  327. INLINE APIRET Mutex::Open(string& mtxname)
  328. {
  329.     APIRET rc;
  330.  
  331.     rc=DosOpenMutexSem(mtxname,(PHMTX)GetPHSEM());
  332.     return rc;
  333. }
  334.  
  335. INLINE APIRET Mutex::Create(string& mtxname, ULONG attr, BOOL32 state)
  336. {
  337.     APIRET rc;
  338.     if (mtxname.length()==0)
  339.     {
  340.     // create an unnamed mutex
  341.     rc=DosCreateMutexSem(NULL,(PHMTX)GetPHSEM(),attr,state);
  342.     }
  343.     else
  344.     {
  345.     // create a named mutex
  346.     rc=DosCreateMutexSem(mtxname,(PHMTX)GetPHSEM(),attr,state);
  347.     }
  348.     return rc;
  349. }
  350.  
  351. //////////////////////////
  352.  
  353. INLINE MutexLock::MutexLock(Mutex& mtx): mutex(mtx)
  354. {
  355.     APIRET rc=mutex.Request();
  356.     if (rc!=0)
  357.     {
  358.     // +++ error
  359.         cerr<<"Error"<<endl;
  360.     }
  361. }
  362.  
  363. INLINE MutexLock::MutexLock(Mutex* mtx): mutex(*mtx)
  364. {
  365.     APIRET rc=mutex.Request();
  366.     if (rc!=0)
  367.     {
  368.         // +++ error
  369.         cerr<<"Error"<<endl;
  370.     }
  371. }
  372.  
  373. INLINE MutexLock::~MutexLock()
  374. {
  375.     APIRET rc=mutex.Release();
  376.     if (rc!=0)
  377.     {
  378.     // +++ error
  379.         cerr<<"Error"<<endl;
  380.     }
  381. }
  382.  
  383. ////////////////////////////
  384.  
  385.  
  386. /*
  387.    Default ctor.  Creates an unnamed, shared, initially set event
  388.    semaphore.
  389.  */
  390. INLINE Event::Event(): Semaphore()
  391. {
  392.     APIRET rc=0;
  393.     rc=DosCreateEventSem(NULL,(PHEV)GetPHSEM(),DEFAULTATTR,DEFAULTSTATE);
  394.     if (rc!=0)
  395.     {
  396.     // error creating event sem
  397.         cerr<<"Error"<<endl;
  398.     }
  399. }
  400.  
  401. /*
  402.    Copy ctor.  opens existing sem.
  403.  */
  404. INLINE Event::Event(const Event& event): Semaphore(event)
  405. {
  406.     APIRET rc=0;
  407.     rc=DosOpenEventSem(NULL,(PHEV)GetPHSEM());
  408.     if (rc!=0)
  409.     {
  410.     // error
  411.         cerr<<"Error"<<endl;
  412.     }
  413. }
  414.  
  415. INLINE Event::Event(string& name, Openmode mode,
  416.             ULONG attr, BOOL32 state):
  417.     Semaphore()
  418. {
  419.     APIRET rc=0;
  420.  
  421.     switch (mode)
  422.     {
  423.     case DONTCARE:
  424.     case OPEN:
  425.     if ((mode==OPEN) && (name.length()==0))
  426.     {
  427.         // error  must open a semaphore using a name.
  428.         cerr<<"Error"<<endl;
  429.     }
  430.     rc=Open(name);
  431.     if (rc==0)
  432.         break;
  433.     if (mode==OPEN)
  434.     {
  435.         if (rc!=0)
  436.         {
  437.         // +++ log and throw
  438.         cerr<<"Error"<<endl;
  439.         }
  440.         break;
  441.     }
  442.     case CREATE:
  443.     rc=Create(name,attr,state);
  444.     if (rc!=0)
  445.     {
  446.         // +++ log and throw
  447.         cerr<<"Error"<<endl;
  448.     }
  449.     break;
  450.     default:
  451.     // +++ log and throw
  452.     ;
  453.         cerr<<"Error"<<endl;
  454.     }
  455. }
  456.  
  457. INLINE Event::~Event()
  458. {
  459.     APIRET rc=DosCloseEventSem((HEV)GetHSEM());
  460.     if (rc!=0)
  461.     {
  462.         cerr<<"Error"<<endl;
  463.     }
  464. }
  465.  
  466. INLINE APIRET Event::Post()
  467. {
  468.     return DosPostEventSem((HEV)GetHSEM());
  469. }
  470.  
  471. INLINE APIRET Event::Wait(ULONG timeout)
  472. {
  473.     return DosWaitEventSem((HEV)GetHSEM(),timeout);
  474. }
  475.  
  476. INLINE APIRET Event::Query(ULONG* postCount)
  477. {
  478.     return DosQueryEventSem((HEV)GetHSEM(),postCount);
  479. }
  480.  
  481. INLINE APIRET Event::Reset(ULONG* postCount)
  482. {
  483.     if (postCount==0)
  484.     {
  485.     ULONG count;
  486.     // ignore the postcount and just reset the sucker.
  487.     return DosResetEventSem((HEV)GetHSEM(),&count);
  488.     }
  489.     else
  490.     {
  491.     return DosResetEventSem((HEV)GetHSEM(),postCount);
  492.     }
  493. }
  494.  
  495. INLINE APIRET Event::Open(string& name)
  496. {
  497.     APIRET rc;
  498.     int filerc;
  499.  
  500.     rc=DosOpenEventSem(name,(PHEV)GetPHSEM());
  501.     return rc;
  502. }
  503.  
  504. INLINE APIRET Event::Create(string& name, ULONG attr, BOOL32 state)
  505. {
  506.     APIRET rc;
  507.     if (name.length()==0)
  508.     {
  509.     // create unnamed shares semaphore
  510.     rc=DosCreateEventSem(NULL,(PHEV)GetPHSEM(),attr,state);
  511.     }
  512.     else
  513.     {
  514.     rc=DosCreateEventSem(name,(PHEV)GetPHSEM(),attr,state);
  515.     }
  516.     return rc;
  517. }
  518.  
  519. #endif
  520.  
  521.